package com.guanji.learn.osss3springboottest.controller;

import cn.hutool.core.util.URLUtil;
import com.amazonaws.HttpMethod;
import com.amazonaws.services.s3.AmazonS3;
import com.amazonaws.services.s3.AmazonS3ClientBuilder;
import com.guanji.learn.osss3springboottest.request.OSSDownloadZipRequest;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;

import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.InputStream;
import java.io.UnsupportedEncodingException;
import java.net.URL;
import java.net.URLConnection;
import java.net.URLDecoder;
import java.nio.charset.StandardCharsets;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;
import java.util.stream.Collectors;
import java.util.zip.ZipEntry;
import java.util.zip.ZipOutputStream;

@RestController
@RequestMapping("/oss/")
public class OSSDownloadZipController {


    /* 1.12.315 创建方式 */
    @Autowired
    private AmazonS3 s3;

    /* 线程池：16 并发，可按 CPU 微调 */
    private final ExecutorService pool = Executors.newFixedThreadPool(16);

    /* 预签名有效期：1 小时 */
    private static final int EXPIRE_SECONDS = 3600;

    /**
     * 批量下载并压缩成 ZIP（流式输出）
     * @param ossDownloadZipRequest   S3 object key 列表
     */
    @PostMapping("/download/zip")
    public void downloadZip(@RequestBody OSSDownloadZipRequest ossDownloadZipRequest,
                            HttpServletResponse resp) throws Exception {

        resp.setContentType("application/zip");
        resp.setHeader("Content-Disposition", "attachment; filename=\"images.zip\"");

        // 1. 预签名 URL
        List<URL> urlList = ossDownloadZipRequest.getFileNames().stream().map(URLUtil::url).collect(Collectors.toList());

        // 2. 并行拉取 + 重命名 + 套文件夹
        try (ZipOutputStream zos = new ZipOutputStream(resp.getOutputStream())) {
            List<Future<Void>> tasks = new ArrayList<>();
            for (URL url : urlList) {
                tasks.add(pool.submit(() -> {
                    String newName = rewriteFileName(url.getPath());
                    String zipEntryName = zipRootFolder() + newName;
                    URLConnection conn = url.openConnection();
                    conn.setConnectTimeout(5000);
                    conn.setReadTimeout(10000);
                    try (InputStream in = conn.getInputStream()) {
                        synchronized (zos) {
                            zos.putNextEntry(new ZipEntry(zipEntryName));
                            byte[] buf = new byte[8192];
                            int len;
                            while ((len = in.read(buf)) != -1) {
                                zos.write(buf, 0, len);
                            }
                            zos.closeEntry();
                        }
                    } catch (IOException e) {
                        throw new RuntimeException("Failed to process " + url.getPath(), e);
                    }
                    return null;
                }));
            }
            // 3. 等待全部完成
            for (Future<Void> f : tasks) {
                f.get();
            }
            zos.finish();
        }
    }

    private String rewriteFileName(String originalKey) throws UnsupportedEncodingException {
        // 1. 取纯文件名
        String fileName = originalKey.substring(originalKey.lastIndexOf('/') + 1);

        // 2. URL 解码（%E4%BD%95… → 汉字）
        fileName = URLDecoder.decode(fileName, String.valueOf(StandardCharsets.UTF_8));

        // 3. 去掉旧时间戳（_20251106165510 这种 14 位）
        String noOldTs = fileName.replaceAll("_\\d{14}(?=\\.)", "");

        // 4. 拼新时间戳
        String ext = noOldTs.contains(".") ? noOldTs.substring(noOldTs.lastIndexOf('.')) : "";
        String base = noOldTs.contains(".") ? noOldTs.substring(0, noOldTs.lastIndexOf('.')) : noOldTs;
        String ts = new SimpleDateFormat("yyyyMMddHHmmss").format(new Date());

        return base + "_" + ts + ext;
    }
    private String zipRootFolder() {
        return "images/";
    }
}
